package crossCount;

import java.io.IOException;
import java.util.Iterator;
import java.util.SortedSet;

import _general.Config;
import _general.geometry.Cross;
import _general.geometry.Edge;
import _general.geometry.EdgeList;
import _general.geometry.Node;
import _general.geometry.Point;
import _general.problem.CrossCount;

public class GenerallyCrossCount extends CrossCount {
	
	public GenerallyCrossCount() {
		super();
		setName("Generally Cross Count");
	}

	public GenerallyCrossCount(SortedSet<Point> pointSet, EdgeList<Edge> activeEdge) {
		super(pointSet, activeEdge);
		setName("Generally Cross Count");
	}

	@Override
	public void start() {
		while(!pointSet.isEmpty()) {
			Point p = pointSet.first();
			pointSet.remove(p);
			
			if (p.getClass().equals(Node.class) && ((Node) p).isStart()){
				
				if (Config.log) System.out.printf("actual Node (%.0f, %.0f) is start Node\n", p.getX(), p.getY());
				
				activeEdge.sortedAdd(((Node) p).getEdge());
				
				Edge successor = activeEdge.getSuccessor(((Node) p).getEdge());
				Edge predecessor = activeEdge.getPredecessor(((Node) p).getEdge());
				
				if(successor != null && ((Node) p).getEdge().isIntersection(successor)){
					
					Cross newCross = ((Node) p).getEdge().getIntersection(successor);
					if(p.getX() < newCross.getX()) {
						if(Config.log) System.out.printf("actual Edge has an intersection with successor (%.0f, %.0f) -> (%.0f, %.0f)\n", successor.getStart().getX(), successor.getStart().getY(), successor.getEnd().getX(), successor.getEnd().getY());
						pointSet.add(newCross);
					}
				}
				
				if(predecessor != null && ((Node) p).getEdge().isIntersection(predecessor)){
					Cross newCross = predecessor.getIntersection(((Node) p).getEdge());
					if (p.getX() < newCross.getX()) {
						if(Config.log) System.out.printf("actual Edge has an intersection with predecessor (%.0f, %.0f) -> (%.0f, %.0f)\n", predecessor.getStart().getX(), predecessor.getStart().getY(), predecessor.getEnd().getX(), predecessor.getEnd().getY());
						pointSet.add(newCross);
					}
				}
				
			} else if (p.getClass().equals(Node.class) && !((Node) p).isStart()){
				
				if(Config.log) System.out.printf("actual Node (%.0f, %.0f) is end Node\n", p.getX(), p.getY());
				
				Edge successor = activeEdge.getSuccessor(((Node) p).getEdge());
				Edge predecessor = activeEdge.getPredecessor(((Node) p).getEdge());
				
				if(successor != null && predecessor != null && successor.isIntersection(predecessor)){
					Cross newCross = predecessor.getIntersection(successor);
					if(p.getX() < newCross.getX()) {
						if(Config.log) System.out.printf("predecessor (%.0f, %.0f) -> (%.0f, %.0f) has an intersection with successor (%.0f, %.0f) -> (%.0f, %.0f)\n", predecessor.getStart().getX(), predecessor.getStart().getY(), predecessor.getEnd().getX(), predecessor.getEnd().getY(), successor.getStart().getX(), successor.getStart().getY(), successor.getEnd().getX(), successor.getEnd().getY());
						pointSet.add(newCross);
					}
				}
				
				activeEdge.remove(((Node) p).getEdge());
				
			} else if (p.getClass().equals(Cross.class)) {
				
				if(Config.log) System.out.printf("actual Node (%.0f, %.0f) is intersection\n", p.getX(), p.getY());
				
				crossCount++;
				
				if(Config.log) System.out.println("CC is now " + crossCount);
//				swapListElements(activeEdge,
//								((Cross) p).getEdge1(),
//								((Cross) p).getEdge2());
				
				activeEdge.swap(((Cross) p).getEdge1(), ((Cross) p).getEdge2());
				
				Edge predecessor = activeEdge.getPredecessor(((Cross) p).getEdge2());
				
				if (Config.log) if (predecessor != null)
					System.out.printf("predecessor is (%.0f, %.0f) -> (%.0f, %.0f)\n", predecessor.getStart().getX(), predecessor.getStart().getY(), predecessor.getEnd().getX(), predecessor.getEnd().getY());
				else
					System.out.println("no predecessor");
				
				if(predecessor != null && ((Cross) p).getEdge2().isIntersection(predecessor)) {
					Cross newCross = predecessor.getIntersection(((Cross) p).getEdge2());
					if(p.getX() < newCross.getX()) {
						if(Config.log) System.out.printf("edge 2 has an intersection with predecessor (%.0f, %.0f) -> (%.0f, %.0f)\n", predecessor.getStart().getX(), predecessor.getStart().getY(), predecessor.getEnd().getX(), predecessor.getEnd().getY());
						pointSet.add(newCross);
					}
				}
				
				Edge successor = activeEdge.getSuccessor(((Cross) p).getEdge1());
				
				if (Config.log) if (successor != null)
					System.out.printf("successor is (%.2f, %.2f) -> (%.2f, %.2f)\n",successor.getStart().getX(), successor.getStart().getY(), successor.getEnd().getX(), successor.getEnd().getY());
				else
					System.out.println("no successor");
				
				if(successor != null && ((Cross) p).getEdge1().isIntersection(successor)) {
					Cross newCross = ((Cross) p).getEdge1().getIntersection(successor);
					if(p.getX() < newCross.getX()) {
						if(Config.log) System.out.printf("edge 1 has an intersection with successor (%.0f, %.0f) -> (%.0f, %.0f)\n", successor.getStart().getX(), successor.getStart().getY(), successor.getEnd().getX(), successor.getEnd().getY());
						pointSet.add(newCross);
					}
				}
				
			} else {
				try {
					throw new IOException();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			if (Config.log){ 
				System.out.println("actual pointset");
				for ( Iterator<Point> i = pointSet.iterator(); i.hasNext(); )
				{
					Point nextPoint = (Point) i.next();
					System.out.printf("(%.0f, %.0f), ", nextPoint.getX(), nextPoint.getY());
				}
				System.out.println();
			}
			/*
			System.out.println("Edge-list");
			for (Iterator i = activeEdge.iterator(); i.hasNext();) {
				Point nextPoint = ((Edge) i.next()).getStart();
				
				System.out.println("(" + nextPoint.getX() + ", " + nextPoint.getY() + "), ");
			}*/
		}
	}
}
